/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.uca.dss.curso2011.grupo1.interfazExtendido;

import java.util.ArrayList;
import java.util.List;
import org.joda.time.LocalDate;
import org.joda.time.LocalTime;
import org.uca.dss.curso2011.grupo1.clases.Ciudad;
import org.uca.dss.curso2011.grupo1.clases.Hora;
import org.uca.dss.curso2011.grupo1.clases.Reserva;
import org.uca.dss.curso2011.grupo1.interfaz.Estado;

/**
 * Clase que implementa InterfazListados
 * @author David
 */
public class ListadosExtendidos implements InterfazListados {

    private Estado estado;
    
    public ListadosExtendidos(List<Hora> horas, List<Reserva> reservas){
           this.estado = new Estado(horas, reservas);
    }

    /**
     * Método que obtiene los itinerarios entre 2 ciudades a una fecha entre las horas deseadas.
     * @param origen Ciudad de origen.
     * @param destino Ciudad de destino.
     * @param fechaSalida fecha de Salida deseada.
     * @param horaSalida Hora de salida mínima.
     * @param horaLlegada Hora de llegada máxima.
     * @return Itinerarios entre las horas indicadas disponibles, en esa fecha.
     */
    public List<Itinerario> getItinerariosEntre(String origen, String destino, LocalDate fechaSalida, LocalTime horaSalida, LocalTime horaLlegada) {

         // Tomamos los itinerarios disponibles para esa fecha.
         List<Itinerario> itinerarios = this.getItinerarios(origen,destino,fechaSalida);
         List<Itinerario> itinerariosRequeridos = new ArrayList<Itinerario> ();

         // Filtramos los itinerarios guardando los que estén entre las horas seleccionadas.
         for (Itinerario itinerario: itinerarios){
            if(itinerario.get(0).getHoraSalida().isAfter(horaSalida.minusMinutes(1)) && itinerario.get(itinerario.size()-1).getHoraLlegada().isBefore(horaLlegada.plusMinutes(1))){
               itinerariosRequeridos.add(itinerario);
            }
         }

         return itinerariosRequeridos;
    }

    /**
     * Método que obtiene los itinerarios entre 2 ciudades a una fecha
     * @param origen Ciudad de origen.
     * @param destino Ciudad de destino.
     * @param fechaSalida fecha de Salida deseada.
     * @return Itinerarios disponibles en la fecha indicada entre las ciudades dadas.
     */
    public List<Itinerario> getItinerarios(String origen, String destino, LocalDate fechaSalida) {

        List<Itinerario> itinerarios = new ArrayList<Itinerario> ();

        //Trayectos Directos
        for (Hora hora: this.estado.obtieneHoras()){
            // Miramos si existe el trayecto.
            if (hora.obtieneTrayecto().existeTrayecto(new Ciudad(origen), new Ciudad(destino))){ 

                InformacionTrayecto informacionTrayecto = new InformacionTrayecto(hora.obtieneTrayecto().obtieneOrigen().obtieneNombre(),
                                                                                  hora.obtieneTrayecto().obtieneDestino().obtieneNombre(),
                                                                                  hora.obtieneHoraSalida(),
                                                                                  hora.obtieneHoraLlegada(),
                                                                                  hora.calculaPrecio());

                 Itinerario itinerario = new ImplementaItinerario();
                 itinerario.add(informacionTrayecto);

                // Comprobamos en cada reserva si hay plazas disponibles
                if(this.estado.obtieneReservas().isEmpty()){
                    itinerarios.add(itinerario);
                }else{
                    boolean disponible = true;

                    for(Reserva reserva: this.estado.obtieneReservas()){
                        if(! reserva.horaDisponible(fechaSalida, hora)){
                           disponible = false;
                        }
                    }

                    if(disponible){
                        itinerarios.add(itinerario);
                    }
                }

            }
        }

        //Trayectos indirectos 1 transbordo.

        for(Hora hora: this.estado.obtieneHoras()){
            // Tomamos las horas con esa ciudad de origen.
            if(hora.obtieneTrayecto().obtieneOrigen().obtieneNombre().equals(origen)){

                Ciudad destinoIntermedio = hora.obtieneTrayecto().obtieneDestino();

                // Buscamos que haya horas de la ciudad destino de la anterior y destino deseado.
                for(Hora hora2: this.estado.obtieneHoras()){
                    if(hora2.obtieneTrayecto().existeTrayecto(destinoIntermedio, new Ciudad(destino))){

                        //Comprobamos que el horario entre ambos trayectos sea mayor de 10 minutos y el primero menor que el segundo.
                        if (hora.obtieneHoraLlegada().isBefore(hora2.obtieneHoraSalida().plusMinutes(10))){

                            InformacionTrayecto informacionTrayecto = new InformacionTrayecto(hora.obtieneTrayecto().obtieneOrigen().obtieneNombre(),
                                                                                              hora.obtieneTrayecto().obtieneDestino().obtieneNombre(),
                                                                                              hora.obtieneHoraSalida(),
                                                                                              hora.obtieneHoraLlegada(),
                                                                                               hora.calculaPrecio());

                            InformacionTrayecto informacionTrayecto2 = new InformacionTrayecto(hora2.obtieneTrayecto().obtieneOrigen().obtieneNombre(),
                                                                                             hora2.obtieneTrayecto().obtieneDestino().obtieneNombre(),
                                                                                             hora2.obtieneHoraSalida(),
                                                                                             hora2.obtieneHoraLlegada(),
                                                                                             hora2.calculaPrecio());

                             Itinerario itinerario = new ImplementaItinerario();
                             itinerario.add(informacionTrayecto);
                             itinerario.add(informacionTrayecto2);

                            // Miramos que haya plazas para ambas
                            if(this.estado.obtieneReservas().isEmpty()){
                                itinerarios.add(itinerario);
                            }else{
                                boolean disponible = true;

                                for(Reserva reserva: this.estado.obtieneReservas()){

                                    if((! reserva.horaDisponible(fechaSalida, hora)) || (! reserva.horaDisponible(fechaSalida, hora2))){
                                       disponible = false;
                                     }

                                   
                                }
                                if (disponible){
                                    itinerarios.add(itinerario);
                                }
                                
                            }
                        }


                    }
                }
            }
        }

        return itinerarios;
    }

}
